package HeartsCard;

import java.awt.*;
import java.awt.event.*;
import java.util.*;

import javax.swing.*;
import javax.swing.border.*;

@SuppressWarnings("serial")
public class MainForm extends JFrame implements Observer, Runnable {

	private ArrayList<CardImage> setCard;
	{
		String s = "/img/";
		String s2 = "/img/b.gif";
		int i = 0;
		this.setCard = new ArrayList<CardImage>();
		
		this.setCard.add(new CardImage(s + "2s.gif", s2, i++, "(2 â™ )"));				
		this.setCard.add(new CardImage(s + "3s.gif", s2, i++, "(3 â™ )"));				
		this.setCard.add(new CardImage(s + "4s.gif", s2, i++, "(4 â™ )"));				
		this.setCard.add(new CardImage(s + "5s.gif", s2, i++, "(5 â™ )"));				
		this.setCard.add(new CardImage(s + "6s.gif", s2, i++, "(6 â™ )"));			
		this.setCard.add(new CardImage(s + "7s.gif", s2, i++, "(7 â™ )"));			
		this.setCard.add(new CardImage(s + "8s.gif", s2, i++, "(8 â™ )"));		
		this.setCard.add(new CardImage(s + "9s.gif", s2, i++, "(9 â™ )"));	
		this.setCard.add(new CardImage(s + "ts.gif", s2, i++, "(10â™ )"));	
		this.setCard.add(new CardImage(s + "js.gif", s2, i++, "(J â™ )"));	
		this.setCard.add(new CardImage(s + "qs.gif", s2, i++, "(Q â™ )"));
		this.setCard.add(new CardImage(s + "ks.gif", s2, i++, "(K â™ )"));
		this.setCard.add(new CardImage(s + "as.gif", s2, i++, "(A â™ )"));
		
		this.setCard.add(new CardImage(s + "2c.gif", s2, i++, "(2 â™£)"));
		this.setCard.add(new CardImage(s + "3c.gif", s2, i++, "(3 â™£)"));
		this.setCard.add(new CardImage(s + "4c.gif", s2, i++, "(4 â™£)"));
		this.setCard.add(new CardImage(s + "5c.gif", s2, i++, "(5 â™£)"));
		this.setCard.add(new CardImage(s + "6c.gif", s2, i++, "(6 â™£)"));
		this.setCard.add(new CardImage(s + "7c.gif", s2, i++, "(7 â™£)"));
		this.setCard.add(new CardImage(s + "8c.gif", s2, i++, "(8 â™£)"));
		this.setCard.add(new CardImage(s + "9c.gif", s2, i++, "(9 â™£)"));
		this.setCard.add(new CardImage(s + "tc.gif", s2, i++, "(10â™£)"));
		this.setCard.add(new CardImage(s + "jc.gif", s2, i++, "(J â™£)"));
		this.setCard.add(new CardImage(s + "qc.gif", s2, i++, "(Q â™£)"));
		this.setCard.add(new CardImage(s + "kc.gif", s2, i++, "(K â™£)"));	
		this.setCard.add(new CardImage(s + "ac.gif", s2, i++, "(A â™£)"));
		
		this.setCard.add(new CardImage(s + "2d.gif", s2, i++, "(2 â™¦)"));
		this.setCard.add(new CardImage(s + "3d.gif", s2, i++, "(3 â™¦)"));
		this.setCard.add(new CardImage(s + "4d.gif", s2, i++, "(4 â™¦)"));
		this.setCard.add(new CardImage(s + "5d.gif", s2, i++, "(5 â™¦)"));
		this.setCard.add(new CardImage(s + "6d.gif", s2, i++, "(6 â™¦)"));
		this.setCard.add(new CardImage(s + "7d.gif", s2, i++, "(7 â™¦)"));
		this.setCard.add(new CardImage(s + "8d.gif", s2, i++, "(8 â™¦)"));
		this.setCard.add(new CardImage(s + "9d.gif", s2, i++, "(9 â™¦)"));			
		this.setCard.add(new CardImage(s + "td.gif", s2, i++, "(10â™¦)"));		
		this.setCard.add(new CardImage(s + "jd.gif", s2, i++, "(J â™¦)"));		
		this.setCard.add(new CardImage(s + "qd.gif", s2, i++, "(Q â™¦)"));			
		this.setCard.add(new CardImage(s + "kd.gif", s2, i++, "(K â™¦)"));				
		this.setCard.add(new CardImage(s + "ad.gif", s2, i++, "(A â™¦)"));				
		
		this.setCard.add(new CardImage(s + "2h.gif", s2, i++, "(2 â™¥)"));				
		this.setCard.add(new CardImage(s + "3h.gif", s2, i++, "(3 â™¥)"));				
		this.setCard.add(new CardImage(s + "4h.gif", s2, i++, "(4 â™¥)"));				
		this.setCard.add(new CardImage(s + "5h.gif", s2, i++, "(5 â™¥)"));			
		this.setCard.add(new CardImage(s + "6h.gif", s2, i++, "(6 â™¥)"));			
		this.setCard.add(new CardImage(s + "7h.gif", s2, i++, "(7 â™¥)"));	
		this.setCard.add(new CardImage(s + "8h.gif", s2, i++, "(8 â™¥)"));	
		this.setCard.add(new CardImage(s + "9h.gif", s2, i++, "(9 â™¥)"));	
		this.setCard.add(new CardImage(s + "th.gif", s2, i++, "(10â™¥)"));		
		this.setCard.add(new CardImage(s + "jh.gif", s2, i++, "(J â™¥)"));		
		this.setCard.add(new CardImage(s + "qh.gif", s2, i++, "(Q â™¥)"));			
		this.setCard.add(new CardImage(s + "kh.gif", s2, i++, "(K â™¥)"));		
		this.setCard.add(new CardImage(s + "ah.gif", s2, i++, "(A â™¥)"));	
	}
	
	private final Color bgColor = new Color(40, 100, 15);
	private final int WIDTH = 900;
	private final int HEIGHT = 700;
	private JLabel statusText;
	private Playing playing;
        private JLabel bg;
	
	private boolean visibleCard = false;
	private final int SPEED = 200;
	
	private String doWhat = "";
	private int indexX = -1;
	private int who = -1;
	private int extraP = 0;
	private boolean isShootingTheMoon = false;
	private ArrayList<Integer> userCanUse;
	private boolean canClick = false;
	
	public MainForm() {
		this.initInterface();
		this.playing = new Playing(this);
		this.setMainPanel();
		this.setVisible(true);
		this.display();
		this.playing.nextPlay();
	}
	
	public void newGame() {
		this.doWhat = "new game";
		new Thread(this).start();
	}
	
	public void newRound() {
		this.doWhat = "new round";
		new Thread(this).start();
	}
	
	protected void userClicking(int indexChosen) {
		this.canClick = false;
		boolean flag = false;
		for(int i = 0; i < this.userCanUse.size(); ++i) 
			if(indexChosen == this.userCanUse.get(i))
				flag = true;
		if(flag) {
			this.doWhat = "bottom";
			this.indexX = indexChosen;
			new Thread(this).start();
		}
		else {
			this.canClick = true;
		}
	}
	
	protected void showPoints() {
		String human = "Human:            = " + this.playing.getTotalA() + " + " + this.playing.getPointA();// + ")";
		String c1 = "\nComputer 1:   = " + this.playing.getTotalB() + " + " + this.playing.getPointB();// + ")"; 
		String c2 = "\nComputer 2:   = " + this.playing.getTotalC() + " + " + this.playing.getPointC();// + ")"; 
		String c3 = "\nComputer 3:   = " + this.playing.getTotalD() + " + " + this.playing.getPointD();// + ")"; 
		String x = human + c1 + c2 + c3;
		
		JOptionPane.showMessageDialog(this, x, "Points of four players!", 
				JOptionPane.INFORMATION_MESSAGE, null);
	}
	
	protected void initInterface() {
		
		this.setLocationRelativeTo(null);// appears in the center of the screen
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//click Exit will end program
		this.setResizable(false);
		this.setTitle("Heart Game");
		
		this.setLocation(70, 35);
		this.setSize(this.WIDTH, this.HEIGHT);
		this.setLayout(new BorderLayout());
		
		//set menu
		JMenuBar menu = new JMenuBar();
			JMenu file = new JMenu("File");
				JMenuItem newGame = new JMenuItem("New Game");
					newGame.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							newGame();
						}
					});
				file.add(newGame);
				file.addSeparator();
				JMenuItem score = new JMenuItem("Score");
					score.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							showPoints();
						}
					});
				file.add(score);
				file.addSeparator();
				JMenuItem exit = new JMenuItem("Exit");
					exit.addActionListener(new ActionListener() {
						public void actionPerformed(ActionEvent e) {
							System.exit(0);
						}
					});
				file.add(exit);
				
				
			menu.add(file);
		this.setJMenuBar(menu);
		
		//sets status
		JToolBar status = new JToolBar();
			JLabel l = new JLabel("You must use one of these cards:");
			l.setForeground(Color.BLUE);
			status.add(l);
			this.statusText = new JLabel(" ");
			this.statusText.setForeground(Color.RED);
			status.add(this.statusText);
			status.setSize(this.getWidth() - 2, 100);
		this.add(status, BorderLayout.SOUTH);
		//this.add(this.mainPanel, BorderLayout.CENTER);
	}
	
	protected void setMainPanel() {
		
		//sets panel in center
		JPanel mainPanel = new JPanel(null);
		mainPanel.setBackground(this.bgColor);
		
		JLabel A, B, C, D;
			A = new JLabel("Human");
			A.setBounds((this.WIDTH/2) - 40, 
					this.getHeight() - 110, 100, 50);
			A.setForeground(Color.LIGHT_GRAY);

			B = new JLabel("Computer 1 ");
			B.setBounds(20, 110, 100, 50);
			B.setForeground(Color.LIGHT_GRAY);
			C = new JLabel("Computer 2 ");
			C.setBounds(400, 1, 100, 30);
			C.setForeground(Color.LIGHT_GRAY);
			D = new JLabel("Computer 3 ");
			D.setBounds(this.getWidth() - 100, 110, 100, 50);
			D.setForeground(Color.LIGHT_GRAY);
			
		mainPanel.add(A);	
		mainPanel.add(B);	
		mainPanel.add(C);	
		mainPanel.add(D);	
		
		//set card positions
		ArrayList<Integer> temp;
		CardImage cardTemp;
		int x, y, plus;
		int width = this.setCard.get(0).getSize().width;
		
		// --- bottom ---
		x = this.WIDTH - 320;
		y = this.HEIGHT - 120 - width;
		plus = -30;
		temp = this.playing.getBottom();
		for(int i = 0; i < temp.size(); ++i) {
			cardTemp = this.setCard.get(temp.get(i));
			cardTemp.setLocation(x, y);
			cardTemp.setOpening(true);
			cardTemp.setVisible(true);
			cardTemp.setBorder(null);
			mainPanel.add(cardTemp);
			x += plus;
		}
		
		// --- left ---
		x = 20;
		y = 150;
		plus = 20;
		temp = this.playing.getLeft();
		for(int i = 0; i < temp.size(); ++i) {
			cardTemp = this.setCard.get(temp.get(i));
			cardTemp.setLocation(x, y);
			cardTemp.setOpening(this.visibleCard);
			cardTemp.setVisible(true);
			cardTemp.setBorder(null);
			mainPanel.add(cardTemp);
			y += plus;
		}
		
		// --- top ---
		x = this.WIDTH - 320;
		y = 30;
		plus = -30;
		temp = this.playing.getTop();
		for(int i = 0; i < temp.size(); ++i) {
			cardTemp = this.setCard.get(temp.get(i));
			cardTemp.setLocation(x, y);
			cardTemp.setOpening(this.visibleCard);
			cardTemp.setVisible(true);
			cardTemp.setBorder(null);
			mainPanel.add(cardTemp);
			x += plus;
		}
		
		// --- right ---
		x = this.WIDTH - width - 30;
		y = 150;
		plus = 20;
		temp = this.playing.getRight();
		for(int i = 0; i < temp.size(); ++i) {
			cardTemp = this.setCard.get(temp.get(i));
			cardTemp.setLocation(x, y);
			cardTemp.setOpening(this.visibleCard);
			cardTemp.setVisible(true);
			cardTemp.setBorder(null);
			mainPanel.add(cardTemp);
			y += plus;
		}
                bg = new JLabel();
                bg.setIcon(new javax.swing.ImageIcon(getClass().getResource("/img/background.jpg")));
                mainPanel.add(bg);
                bg.setBounds(0, 0, 900, 700);
		
		//add to JFrame
		if(this.getContentPane().getComponentCount() > 1)
			this.getContentPane().remove(1);
		this.add(mainPanel, BorderLayout.CENTER);
	}
	
	private void goBottomCenter(int index) throws InterruptedException {
		
		CardImage t = this.setCard.get(index);
		t.setOpening(true);
		int y = t.getLocation().y;				
		while(y > 350) {
			y -= 25;
			t.setLocation(400, y);
			Thread.sleep(20);
		}
	}
	
	private void goTopCenter(int index) throws InterruptedException {
		
		CardImage t = this.setCard.get(index);
		t.setOpening(true);
		int y = t.getLocation().y;		
		while(y < 180) {
			y += 25;
			t.setLocation(400, y);
			Thread.sleep(20);
		}
	}
	
	private void goLeftCenter(int index) throws InterruptedException {
		
		CardImage t = this.setCard.get(index);
		t.setOpening(true);
		int x = t.getLocation().x;		
		while(x < 295) {
			x += 25;
			t.setLocation(x, 270);
			Thread.sleep(20);
		}
	}
	
	private void goRightCenter(int index) throws InterruptedException {
		
		CardImage t = this.setCard.get(index);
		t.setOpening(true);
		int x = t.getLocation().x + 7;		
		while(x > 515) {
			x -= 25;
			t.setLocation(x, 270);
			Thread.sleep(20);
		}
	}
	

	@Override
	public void run() {
		
		if(this.doWhat.equals("notice")) {
			this.setCard.get(this.indexX).setBorder(new LineBorder(Color.BLUE, 4));
			try {
				Thread.sleep(this.SPEED * 5);
				for(int i = 0; i < this.playing.getCardTurning().size(); ++i) {
					this.setCard.get(this.playing.getCardTurning().get(i))
						.setVisible(false);
				}
				
				System.out.println();
				for(int i = 0; i< this.playing.getCardTurning().size(); ++i) {
					System.out.printf("%-5s ", 
							this.setCard.get(this.playing.getCardTurning().get(i)).NAME);
				}
				String s = "*";
				String p = "";
				if(this.extraP > 0) p = "+" + String.valueOf(this.extraP) +" points" ;
				if(this.who == 0) s = "Human";
				else if(this.who == 1) s = "Computer 1";
				else if(this.who == 2) s = "Computer 2";
				else if(this.who == 3) s = "Computer 3";
				System.out.printf("   => Loser: %-10s %-5s  %s", s, this.setCard.get(this.indexX).NAME, p);
				
				if(this.isShootingTheMoon) {
					System.out.printf("\nCongratulating %s on Shooting the Moon!", s);
				}
				
				this.playing.getCardTurning().clear();
				Thread.sleep(this.SPEED);
				this.playing.nextPlay();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
		}
		else if(this.doWhat.equals("left")) {
			try {
				this.goLeftCenter(this.indexX);
				Thread.sleep(this.SPEED);
				this.playing.nextPlay();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		else if(this.doWhat.equals("top")) {
			try {
				this.goTopCenter(this.indexX);
				Thread.sleep(this.SPEED);
				this.playing.nextPlay();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		else if(this.doWhat.equals("right")) {
			try {
				this.goRightCenter(this.indexX);
				Thread.sleep(this.SPEED);
				this.playing.nextPlay();
			} catch (InterruptedException e) {

				e.printStackTrace();
			}
		}
		else if(this.doWhat.equals("bottom")) {
			try {
				this.goBottomCenter(this.indexX);
				Thread.sleep(this.SPEED);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			this.playing.humanPlay(this.indexX);
			return;
		}
		else if(this.doWhat.equals("new round")) {
			this.playing.startNewRound();
			this.setMainPanel();
			this.display();
			this.playing.nextPlay();
		}
		else if(this.doWhat.equals("new game")) {
			System.out.printf("\n|========== End Game ==========|\n\n");
			MainForm.main(new String[] {""});
			this.dispose();
		}
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public void update(Observable arg0, Object arg1) {
		if(arg1 instanceof Integer[]) {
			Integer[] temp = (Integer[]) arg1;
			this.doWhat = "notice";
			this.who = temp[0];
			this.indexX = temp[1];
			this.extraP = temp[2];
			if(temp[3] == 1) this.isShootingTheMoon = true;
			else this.isShootingTheMoon = false;
			new Thread(this).start();
		}
		else if(arg1 instanceof ArrayList<?>) {
			this.doWhat = "";
			this.indexX = -1;
			this.userCanUse = (ArrayList<Integer>) arg1;
			String s = "  ";
			for(int i = 0; i < this.userCanUse.size(); ++i) {
				s += this.setCard.get(this.userCanUse.get(i)).NAME + "  ";
			}
			this.statusText.setText(s);
			this.canClick = true;
		}
		else if(arg1 instanceof String) {
			String[] s = ((String) arg1).split(" ");
			this.doWhat = s[0];
			this.indexX = Integer.parseInt(s[1]);
			new Thread(this).start();
		}
		else if(arg1 instanceof Boolean) {
			System.out.printf("\n\nTotal Points:  Human = %d  ,  Computer_1 = %d  ,  Computer_2 = %d  , Computer_3 = %d\n", 
					this.playing.getTotalA() + this.playing.getPointA(),
					this.playing.getTotalB() + this.playing.getPointB(),
					this.playing.getTotalC() + this.playing.getPointC(),
					this.playing.getTotalD() + this.playing.getPointD());
			System.out.printf("|------------------------------------- End ------------------------------------------------|\n\n\n");
			this.showPoints();
			if((Boolean) arg1) this.newRound();
		}
	}
	
	public void display() {
		System.out.printf("|------------------------------------- Start ----------------------------------------------|\n");
		System.out.printf("%-12s", "Human: ");
		for(int i = 0; i<13; ++ i)
			System.out.printf("%-6s", this.setCard.get(this.playing.getBottom().get(i)).NAME);
		System.out.printf("\n%-12s", "Computer 1: ");
		for(int i = 0; i<13; ++ i)
			System.out.printf("%-6s", this.setCard.get(this.playing.getLeft().get(i)).NAME);
		System.out.printf("\n%-12s", "Computer 2:");
		for(int i = 0; i<13; ++ i)
			System.out.printf("%-6s", this.setCard.get(this.playing.getTop().get(i)).NAME);
		System.out.printf("\n%-12s", "Computer 3: ");
		for(int i = 0; i<13; ++ i)
			System.out.printf("%-6s", this.setCard.get(this.playing.getRight().get(i)).NAME);
		System.out.println();
	}
	
///	-----------------------------------------------------------------------------------	
///	-----------------------------------------------------------------------------------
	private class CardImage extends JButton implements ActionListener {

		private final int INDEX;
		private final int WIDTH;
		private final int HEIGHT;
		private String opening;
		private String closing;
		private boolean isOpening;
		private final String NAME;
		
		public CardImage(String opening, String closing, int index, 
				String name, boolean isOpening) {
			this.INDEX = index;
			this.opening = opening;
			this.closing = closing;
			this.setOpening(isOpening);
			this.NAME = name;
			this.WIDTH = 73;
			this.HEIGHT = 100;
			this.setSize(this.WIDTH, this.HEIGHT);
			this.addActionListener(this);
			this.setContentAreaFilled(false);
		}
		
		public CardImage(String opening, String closing, int index, String name) {
			this(opening, closing, index, name, true);
		}
		
		@Override
		public void actionPerformed(ActionEvent arg0) {
			if(canClick) {
				userClicking(this.INDEX);
			}
		}

		public void setOpening(boolean isOpening) {
			this.isOpening = isOpening;
			if(this.isOpening) this.setIcon(new javax.swing.ImageIcon(getClass().getResource(this.opening)));
			else this.setIcon(new javax.swing.ImageIcon(getClass().getResource(this.closing)));
		}
	}
///	-----------------------------------------------------------------------------------	
///	-----------------------------------------------------------------------------------
	
	/**
	 * @author LÃª Duy DÅ©ng
	 * @Class D07THA3
	 */
	public static void main(String[] args) {
		System.out.printf("Start new the Heart game!!!\n");
		new MainForm();
	}
}
